/******************************************************************************
 * Copyright (c) 2024 Huawei Technologies Co., Ltd.
 * oeAware is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 ******************************************************************************/ 
#ifndef __UTILS_H__
#define __UTILS_H__


#include <vector>
#include <map>
#include <mutex>

#include <log4cplus/log4cplus.h>

#define DEBUG(fmt) LOG4CPLUS_DEBUG(logger.get(), fmt)
#define INFO(fmt)  LOG4CPLUS_INFO(logger.get(), fmt)
#define WARN(fmt)  LOG4CPLUS_WARN(logger.get(), fmt)
#define ERROR(fmt) LOG4CPLUS_ERROR(logger.get(), fmt)
#define FATAL(fmt) LOG4CPLUS_FATAL(logger.get(), fmt)

class Logger {
public:
    Logger(std::string name);
    void init();
    log4cplus::Logger get() {
        return logger;
    }
    void setLogLevel(log4cplus::LogLevel log_level) {
        logger.setLogLevel(log_level);
    }
private:
    log4cplus::Logger logger;
    log4cplus::Initializer initalizer;
};

extern Logger logger;

#define DEFAULT_CFGO_CONFIG_PATH "/etc/cfgo/cfgo.ini"
#define INVALID_PID -1

typedef struct {
    std::string name;
    unsigned long offset;
    int count;
} AddrInfo;


typedef struct {
    int64_t ts;
    std::map<unsigned long, AddrInfo> addrs;
    std::map<std::string, std::map<unsigned long, int>> funcs;
} Profile;
enum APP_STATUS {
    UNOPTIMIZED,            // 未优化状态
    NEED_OPTIMIZED,         // 待优化状态，优先使用动态profile，其次开箱profile
    // DEFAULT_OPTIMIZED,      // 已经过开箱profile优化
    // DYNAMIC_OPTIMIZED       // 已经过动态profile优化
    OPTIMIZED               // 已优化状态
};

typedef struct app_config {
    std::string app_name;
    std::string full_path;
    int current_pid;             // app当前运行进程的pid
    char build_id[20];           // app二进制对应的buildid，用于校验采样对象和优化对象是否一致

    Profile     profile;         // app对应profile数据
    std::string profile_path;    // app对应profile文件路径
    std::mutex  profile_mtx;     // collector和tuner操作profile的互斥锁

    std::string default_profile; // 开箱profile
    APP_STATUS  status;
    std::string bolt_options;
    app_config *next;
} app_config;

typedef struct {
    std::string ini_path;

    log4cplus::LogLevel log_level;
    int sampling_strategy;
    int high_load_threshold;
    int collector_sampling_period;
    int collector_sampling_freq;
    int collector_dump_data_threshold;
    int collector_data_aging_time;
    std::string tuner_tool; 
    int tuner_check_period;
    std::string tuner_profile_dir;
    int tuner_optimizing_strategy;
    int tuner_optimizing_condition;

    app_config *app;
} global_config;

typedef struct {
    std::string cmd_log;
    int ret;
} exec_result;

extern global_config *configs;
extern void cleanup_configs();
extern int parse_cfgo_ini(std::string ini_path);
extern int get_target_pid(app_config *app);
extern std::vector<int> update_pid_in_configs();
extern exec_result exec_cmd(std::string cmd);
#endif
